package com.mazaiting.instructions.comparisons;

import com.mazaiting.instructions.base.NoOperandsInstruction;
import com.mazaiting.rtda.MtFrame;
import com.mazaiting.rtda.MtOperandStack;

/**
 * 用于比较float变量
 *
 * @author mazaiting
 * @since 2021/8/15
 */
public class FCmpInstruction {

    /**
     * 单精度比较
     * 由于浮点数计算有可能产生NaN（Not a Number）值，所以比较两个浮点数时，除了大于、等于、小于之外，
     * 还有第4种结果：无法比较
     * @param frame 栈帧
     * @param flag true: 压入 1; false: 压入 -1
     */
    private static void fCmp(MtFrame frame, boolean flag) {
        MtOperandStack stack = frame.getOperandStack();
        float v1 = stack.popFloat();
        float v2 = stack.popFloat();
        if (v2 > v1) {
            stack.pushInt(1);
        } else if (v1 == v2) {
            stack.pushInt(0);
        } else if (v2 < v1) {
            stack.pushInt(-1);
        } else if (flag) {
            stack.pushInt(1);
        } else {
            stack.pushInt(-1);
        }
    }

    /**
     * 由于浮点数计算有可能产生NaN（Not a Number）值，所以比较两个浮点数时，除了大于、等于、小于之外，
     * 还有第4种结果：无法比较
     */
    public static class FCmpG extends NoOperandsInstruction {
        @Override
        public void execute(MtFrame frame) {
            fCmp(frame, true);
        }
    }

    /**
     * 由于浮点数计算有可能产生NaN（Not a Number）值，所以比较两个浮点数时，除了大于、等于、小于之外，
     * 还有第4种结果：无法比较
     */
    public static class FCmpL extends NoOperandsInstruction {
        @Override
        public void execute(MtFrame frame) {
            fCmp(frame, false);
        }
    }
}
